package com.xing.web;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.xing.common.MessageManager;
import com.xing.config.ds.rw.common.DbContextHolder;
import com.xing.config.properties.DatabaseServersProperties;
import com.xing.dao.one.OneUserDao;
import com.xing.dao.two.TwoUserDao;
import com.xing.entity.User;
import com.xing.enumeration.DBTypeEnum;
import com.xing.service.ProfileAnnotationService;
import com.xing.service.db.IUserService;
import com.xing.service.mq.Sender;
import com.xing.vo.MessageVo;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.assertj.core.util.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * Created by Bradish7Y on 2017/8/22.
 */
@RestController
@RequestMapping("/test")
@Profile({"dev", "prod"})
public class TestController {
    public static final Logger log = LoggerFactory.getLogger(TestController.class);

    /**
     * 测试profile注解，根据application.yaml中的active(maven配置的环境)，来判断是否创建bean
     */
    @ApiOperation(value = "测试@profile注解", notes = "")
    @RequestMapping("/profile")
    public String profile() {

        profileAnnotationService.exec();

        return "ok";
    }

    /**
     * 测试2ConfigurationProperties和@Validated
     */
    @RequestMapping("/prop")
    @ResponseBody
    public String prop(Model model) {
        log.info(databaseServersProperties.getServers().toString());
        log.info(databaseServersProperties.getId());
        return "ok";
    }

    /**
     * 测试httpMessageConvert
     */
    @RequestMapping("/httpmessageconvert")
    @ResponseBody
    public MessageVo httpmessageconvert(Model model) {
        MessageVo messageVo = new MessageVo();
        messageVo.setId(123);
        messageVo.setUsername("bradish76");
        messageVo.setEmail("abc@gmail.com");

        return messageVo;
    }


    /**
     * 测试httpMessageConvert
     */
    @RequestMapping("/error")
    @ResponseBody
    public String mockError(Model model) {
        int a = 1 / 0;
        return "ok";
    }

    /**
     * test redis
     */
    @ApiOperation(value = "redis测试put操作", notes = "输入key、value")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "key", value = "redis key", required = true, dataType = "String"),
            @ApiImplicitParam(name = "value", value = "redis value", required = true, dataType = "String")
    })
    @RequestMapping("/redis/put/{key}/{value}")
    @ResponseBody
    public String redisPut(Model model, @PathVariable String key, @PathVariable String value) {
        stringRedisTemplate.opsForValue().set(key, value);
        return "ok";
    }

    /**
     * test redis
     */
    @RequestMapping("/redis/get/{key}")
    @ResponseBody
    public String redisGet(Model model, @PathVariable String key) {

        return stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * 测试缓存
     */
    @RequestMapping("/cache/get")
    @ResponseBody
    @Cacheable("testCache")
    public String cache(Model model) {
        log.info("get data from db....");
        return "ok";
    }

    @RequestMapping("/mq/put/{msg}")
    @ResponseBody
    public String mqSend(Model model, @PathVariable String msg) {
        sender.send(msg);
        log.info("send a message to rabbitmq");
        return "ok";
    }


    @RequestMapping("/session/{msg}")
    @ResponseBody
    public String session(HttpSession session, @PathVariable String msg) {
        session.setAttribute("session", msg);
        log.info("test session");
        return "ok";
    }

    @RequestMapping("/session/shiro/get")
    @ResponseBody
    public String sessionGet() throws Exception {

        Subject currentUser = SecurityUtils.getSubject();
        Session session = currentUser.getSession();

        return String.valueOf(session.getAttribute("session"));
    }

    @RequestMapping("/template/rest/{key}")
    @ResponseBody
    public String rest(@PathVariable String key) {
        String s = restTemplate.getForObject("http://localhost/test/redis/get/{key}", String.class, key);

        return s;
    }


    /**
     * 多数据源测试
     */
    @RequestMapping("/mybatis/{source}/users")
    @ResponseBody
    public List<User> listAll(HttpSession session, @PathVariable int source) {
        List<User> ret = Lists.newArrayList();
        if (source == 1) {
            ret = oneUserDao.listUser();
        } else if (source == 2) {
            ret = twoUserDao.listUser();
        }
        log.info("test mybatis from db:{}, ret{}", source, ret.toString());

        return ret;
    }

    @RequestMapping("/mybatis/{source}/insert")
    @ResponseBody
    public int insert(HttpSession session, @PathVariable char source) {
        User u = new User();
        u.setUsername("test_" + source);
        u.setPassword("" + System.currentTimeMillis());
        u.setSalt("abcdef");

        int ret = -1;
        if (source == 1) {
            ret = oneUserDao.insert(u);
        } else if (source == 2) {
            ret = twoUserDao.insert(u);
        }

        log.info("insert into db:{}, ret:{}", source, ret);
        return ret;
    }

    /**
     * 多数据源-读写
     */
    @RequestMapping("/mybatis/rw/{source}/users")
    @ResponseBody
    public List<User> listAllForRW(HttpSession session, @PathVariable char source) {
        List<User> ret = Lists.newArrayList();
        if (source == 'r') {
            DbContextHolder.setDbType(DBTypeEnum.READ);
            ret = iUserService.selectList(new EntityWrapper<User>() {
            });
            DbContextHolder.clearDbType();
        } else if (source == 'w') {
            DbContextHolder.setDbType(DBTypeEnum.WRITE);
            ret = iUserService.selectList(new EntityWrapper<User>() {
            });
            DbContextHolder.clearDbType();
        }
        log.info("test mybatis from db:{}, ret{}", source, ret.toString());

        return ret;
    }

    @RequestMapping("/mybatis/rw/{source}/insert")
    @ResponseBody
    public boolean insertForRW(HttpSession session, @PathVariable char source) {
        User u = new User();
        u.setUsername("test_" + source);
        u.setPassword("" + System.currentTimeMillis());
        u.setSalt("abcdef");

        boolean ret = false;
        if (source == 'r') {
            DbContextHolder.setDbType(DBTypeEnum.READ);
            ret = iUserService.insert(u);
            DbContextHolder.clearDbType();
        } else if (source == 'w') {
            DbContextHolder.setDbType(DBTypeEnum.WRITE);
            ret = iUserService.insert(u);
            DbContextHolder.clearDbType();
        }

        log.info("insert into db:{}, ret:{}", source, ret);
        return ret;
    }

    @RequestMapping("/mybatis/rw/{source}/page/{size}/{current}")
    @ResponseBody
    public Page<User> page(@PathVariable int current, @PathVariable int size, @PathVariable char source) {
        List<User> ret = Lists.newArrayList();
        Page<User> page = new Page<>(current, size, "id");
        page.setAsc(false);
        if (source == 'r') {
            DbContextHolder.setDbType(DBTypeEnum.READ);

            page = iUserService.selectPage(page, new EntityWrapper<User>() {
            });
            DbContextHolder.clearDbType();
        } else if (source == 'w') {
            DbContextHolder.setDbType(DBTypeEnum.WRITE);
            page = iUserService.selectPage(page, new EntityWrapper<User>() {
            });
            DbContextHolder.clearDbType();
        }
        log.info("test page from db:{}, ret{}", source, ret.toString());

        return page;
    }

    /**
     * 后台获取国际化信息
     */
    @GetMapping("/message")
    public String getMessage(String key, String msg) {
        return MessageManager.getMessage(key, msg);
    }

    @Resource
    private ProfileAnnotationService profileAnnotationService;

    @Resource
    private DatabaseServersProperties databaseServersProperties;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private Sender sender;

    @Resource
    private TwoUserDao twoUserDao;

    @Resource
    private OneUserDao oneUserDao;

    @Resource
    private IUserService iUserService;

    @Resource
    private RestTemplate restTemplate;

}
